package org.linlinjava.litemall.wx.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.ResponseUtil.ListResponse;
import org.linlinjava.litemall.core.util.ResponseUtil.Response;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.PageTools;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.util.WxResponseEnum;
import org.linlinjava.litemall.wx.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.db.beans.Constants.*;
import static org.linlinjava.litemall.db.beans.Constants.LOG_GIFTCARD_SUBSCRIBE_GIVE;

/**
 * @author ：lilu
 * @description：用户积分操作
 */
@Service
@RequiredArgsConstructor
public class WxIntegralService {

    @Value("${sys.datetime}")
    public String SysDateTime;


    private final LitemallUserService litemallUserService;

    private final LitemallIntegralLogService integralLogService;

    private final LitemallOrderGoodsService orderGoodsService;

    private final LitemallOrderService litemallOrderService;

    private final LumiereSubscribeUserLogService lumiereSubscribeUserLogService;

    private final LumierePayMemberUserLogService lumierePayMemberUserLogService;

    private final LumiereSubscribeService lumiereSubscribeService;

    private final LitemallDistributionLogService litemallDistributionLogService;

    private final LitemallDistributionDetailService litemallDistributionDetailService;

    /**
     * 积分信息
     *
     * @return
     */
    public Response<IntegralIndexResponse> index(Integer userId) {
        IntegralIndexResponse response = new IntegralIndexResponse();

        LitemallUser user = litemallUserService.findById(userId);
        if (user == null) {
            return ResponseUtil.badArgument(WxResponseEnum.NOT_FIND_USER);
        }

        response.setPoints(user.getPoints());
        String config = SystemConfig.getConfig(SystemConfig.LITEMALL_INTEGRAL_AMOUNT);
        response.setExchangeRatio(new BigDecimal(config));
        return ResponseUtil.ok(response);
    }

    /**
     * 积分兑换
     *
     * @return
     */
    @Transactional
    public Response<Object> exchange(Integer userId, IntegralExchangeRequest request){
    	LitemallUser user = litemallUserService.findById(userId);
    	if(user == null){
    		return ResponseUtil.badArgument(WxResponseEnum.NOT_FIND_USER);
    	}

    	BigDecimal points = user.getPoints();
    	//需要兑换的积分
    	BigDecimal changePoints = request.getChangePoints();
    	if(points.compareTo(changePoints)<0) {
    		return ResponseUtil.badArgument(WxResponseEnum.INTEGRAL_EXCHANGE_EXCEED);
    	}

    	BigDecimal remainPoints = points.subtract(changePoints);
    	String config = SystemConfig.getConfig(SystemConfig.LITEMALL_INTEGRAL_AMOUNT);
    	BigDecimal changeAmount = changePoints.multiply(new BigDecimal(config));

    	//修改积分
		LitemallUser update = new LitemallUser();
		update.setId(userId);
		update.setPoints(remainPoints);
		update.setAvailableAmount(user.getAvailableAmount().add(changeAmount));
		litemallUserService.updateById(update);

		//添加积分记录
		LitemallIntegralLog log = new LitemallIntegralLog();
		log.setUserId(userId);
		log.setType(Constants.INTEGRAL_LOG_TYPE_MINUS);
		log.setPoints(remainPoints);
		log.setChangePoints(BigDecimal.ZERO.subtract(changePoints));
		integralLogService.add(log);

    	return ResponseUtil.ok();
    }


    public Response integralChangeLog(Integer userId, Integer page, Integer limit) {
        List<LitemallIntegralLog> integralLogs = integralLogService.list(Wrappers.lambdaQuery(LitemallIntegralLog.class)
                .eq(LitemallIntegralLog::getUserId, userId)
                .orderByDesc(LitemallIntegralLog::getAddTime));

        //视图VO
        /*List< WxIntegralChangeLogVo> wxIntegralChangeLogVos = CollUtil.newArrayList();
            //系统添加、减少
            List<LitemallIntegralLog> integralLogList = integralLogService.list(Wrappers.lambdaQuery(LitemallIntegralLog.class)
                    .eq(LitemallIntegralLog::getUserId, userId)
                    .in(LitemallIntegralLog::getType, 5,6)
                    .orderByDesc(LitemallIntegralLog::getAddTime));
            integralLogList.stream().forEach(integralLog -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder().build();
                BeanUtils.copyProperties(integralLog, wxIntegralChangeLogVo);
                wxIntegralChangeLogVo.setChangePoints(integralLog.getChangePoints());
                wxIntegralChangeLogVo.setUseType(1);
                if (integralLog.getOrderId() != null) {
                    wxIntegralChangeLogVo.setGoodsName(orderGoodsService.queryByOid(integralLog.getOrderId()).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()));
                }
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });

            //购买订阅
            List<LumiereSubscribeUserLog> lumiereSubscribeUserLogList = lumiereSubscribeUserLogService.list(Wrappers.lambdaQuery(LumiereSubscribeUserLog.class)
                    .eq(LumiereSubscribeUserLog::getUserId, userId)
                    .eq(LumiereSubscribeUserLog::getPayType, 3)
                    .orderByDesc(LumiereSubscribeUserLog::getAddTime));
            lumiereSubscribeUserLogList.stream().forEach(subscribeUserLog -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder()
                        .useType(3)
                        .subscribeName(subscribeUserLog.getSubscribeName())
                        .changePoints(BigDecimal.valueOf(subscribeUserLog.getPoint()))
                        .addTime(subscribeUserLog.getAddTime())
                        .build();
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });

            //购买付费会员
            List<LumierePayMemberUserLog> lumierePayMemberUserLogList = lumierePayMemberUserLogService.list(Wrappers.lambdaQuery(LumierePayMemberUserLog.class)
                    .eq(LumierePayMemberUserLog::getUserId, userId)
                    .eq(LumierePayMemberUserLog::getPayType, 4)
                    .orderByDesc(LumierePayMemberUserLog::getAddTime));
            lumierePayMemberUserLogList.stream().forEach(payMemberUserLog -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder()
                        .useType(4)
                        .payMemberName(payMemberUserLog.getPayMemberName())
                        .changePoints(payMemberUserLog.getPoint())
                        .addTime(payMemberUserLog.getAddTime())
                        .build();
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });

            //积分兑换 商品
            List<LitemallOrder> litemallOrderList = litemallOrderService.list(Wrappers.lambdaQuery(LitemallOrder.class)
                    .eq(LitemallOrder::getUserId, userId)
                    .eq(LitemallOrder::getPayType, PAY_TYPE_POINT_EXCHANGE)
                    .orderByDesc(LitemallOrder::getAddTime));
            litemallOrderList.stream().forEach(litemallOrder -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder()
                        .useType(5)
                        .orderId(litemallOrder.getId())
                        .goodsName(orderGoodsService.queryByOid(litemallOrder.getId()).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()))
                        .addTime(litemallOrder.getAddTime())
                        .changePoints(litemallOrder.getPoints())
                        .build();
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });

            //兑换商品退还「积分退还」
            List<LitemallOrder> litemallRefundOrderList = litemallOrderService.list(Wrappers.lambdaQuery(LitemallOrder.class)
                    .eq(LitemallOrder::getUserId, userId)
                    .eq(LitemallOrder::getRefundStatus, 3)
                    .eq(LitemallOrder::getPayType, PAY_TYPE_POINT_EXCHANGE)
                    .orderByDesc(LitemallOrder::getAddTime));
            litemallRefundOrderList.stream().forEach(litemallOrder -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder()
                        .useType(6)
                        .orderId(litemallOrder.getId())
                        .goodsName(orderGoodsService.queryByOid(litemallOrder.getId()).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()))
                        .addTime(litemallOrder.getAddTime())
                        .changePoints(litemallOrder.getPoints())
                        .build();
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });
            //订单商品退还「积分退还」
            List<LitemallOrder> litemallREFUNDOrderList = litemallOrderService.list(Wrappers.lambdaQuery(LitemallOrder.class)
                    .eq(LitemallOrder::getUserId, userId)
                    .eq(LitemallOrder::getRefundStatus, 3)
                    .eq(LitemallOrder::getPayType, PAY_TYPE_POINT_EXCHANGE)
                    .orderByDesc(LitemallOrder::getAddTime));
            litemallREFUNDOrderList.stream().forEach(litemallOrder -> {
                WxIntegralChangeLogVo wxIntegralChangeLogVo = WxIntegralChangeLogVo.builder()
                        .useType(7)
                        .orderId(litemallOrder.getId())
                        .goodsName(orderGoodsService.queryByOid(litemallOrder.getId()).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()))
                        .addTime(litemallOrder.getAddTime())
                        .changePoints(litemallOrder.getPoints())
                        .build();
                wxIntegralChangeLogVos.add(wxIntegralChangeLogVo);
            });
        List<WxIntegralChangeLogVo> collect =wxIntegralChangeLogVos.stream().sorted(Comparator.comparing(WxIntegralChangeLogVo::getAddTime).reversed()).collect(Collectors.toList());*/
        //分页
        PageTools pageTools = PageTools.builder().build();
        pageTools.pageTools(page,limit,integralLogs);
        return ResponseUtil.ok(pageTools);
    }

    /**
     * 积分兑换
     * @return
     */
    public Response<ListResponse<IntegralListLogResponse>> ListLog(Integer userId, Byte type, Integer page, Integer size, String sort, String order) {
        List<IntegralListLogResponse> responseList = new ArrayList<>();
        List<LitemallIntegralLog> logList = integralLogService.querySelectiveList(userId, type, page, size, sort, order);
        if (!CollectionUtils.isEmpty(logList)) {
            for (LitemallIntegralLog litemallIntegralLog : logList) {
                IntegralListLogResponse response = new IntegralListLogResponse();
                BeanUtils.copyProperties(litemallIntegralLog, response);
                Integer orderId = litemallIntegralLog.getOrderId();
                String goodsNames = "";
                if (orderId != null) {
                    List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(orderId);
                    for (int i = 0; i < orderGoods.size(); i++) {
                        goodsNames += orderGoods.get(i).getGoodsName();
                    }

                    response.setOrderId(orderId);
                }

                response.setGoodsNames(goodsNames);
                responseList.add(response);

                if (response.getPoints().compareTo(BigDecimal.ZERO) == 0) {
                    response.setPoints(new BigDecimal(0));
                }else{
                    response.setPoints(new BigDecimal(response.getPoints().intValue()));
                }

                if (response.getChangePoints().compareTo(BigDecimal.ZERO) == 0) {
                    response.setChangePoints(new BigDecimal(0));
                }else{
                    response.setChangePoints(new BigDecimal(response.getChangePoints().intValue()));
                }

                String concerning = null;
                if (litemallIntegralLog.getType() == LOG_GIFTCARD_CONSUME) {
                    if (litemallIntegralLog.getOrderId() != null) {
                        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(litemallIntegralLog.getOrderId());
                        for (int i = 0; i < orderGoods.size(); i++) {
                            concerning = orderGoods.get(i).getGoodsName() ;

                            if(i != orderGoods.size() - 1){
                                concerning += ",";
                            }
                        }
                    }
                    response.setConcerning(concerning);
                } else{
                    if (litemallIntegralLog.getType() == LOG_GIFTCARD_SUBSCRIBE_CONSUME) {  //消费对象是订阅
                        if (litemallIntegralLog.getOrderId() != null) {
                            LumiereSubscribe subscribe = lumiereSubscribeService.findById(litemallIntegralLog.getOrderId());
                            if (subscribe != null) {
                                concerning = "订阅了--" + subscribe.getName();
                            }
                        }
                    } else if (litemallIntegralLog.getType() == LOG_GIFTCARD_SUBSCRIBE_RENEVAL) {  //消费对象是订阅
                        if (litemallIntegralLog.getOrderId() != null) {
                            LumiereSubscribe subscribe = lumiereSubscribeService.findById(litemallIntegralLog.getOrderId());
                            if (subscribe != null) {
                                concerning = "续订了--" + subscribe.getName();
                            }
                        }
                    } else if (litemallIntegralLog.getType() == LOG_GIFTCARD_SUBSCRIBE_GIVE) {  //消费对象是订阅
                        if (litemallIntegralLog.getOrderId() != null) {
                            LumiereSubscribe subscribe = lumiereSubscribeService.findById(litemallIntegralLog.getOrderId());
                            if (subscribe != null) {
                                concerning = "赠送了--" + subscribe.getName();
                            }
                        }
                    }

                }
                response.setConcerning(StrUtil.isBlank(concerning)?"":concerning);
            }
        }
        return ResponseUtil.okList(responseList);
    }


    public Response detailsIntegral(Integer userId,Integer id) {
        IntegralLogVo integralLogVo =integralLogService.selectJoinOne(IntegralLogVo.class,new MPJLambdaWrapper<LitemallIntegralLog>()
                .selectAll(LitemallIntegralLog.class)
                .selectAs(LitemallOrder::getId,IntegralLogVo::getOrderId)
                .selectAs(LitemallOrderGoods::getGoodsName,IntegralLogVo::getGoodsName)
                .selectAs(LitemallShop::getName,IntegralLogVo::getShopName)
                .leftJoin(LitemallRechargeConsumption.class,LitemallRechargeConsumption::getId,LitemallIntegralLog::getConsumptionId)
                .leftJoin(LitemallOrder.class,LitemallOrder::getId,LitemallRechargeConsumption::getOrderId)
                .leftJoin(LitemallOrderGoods.class,LitemallOrderGoods::getOrderId,LitemallOrder::getId)
                .leftJoin(LitemallShop.class,LitemallShop::getId,LitemallOrder::getShopId)
                .eq(LitemallIntegralLog::getUserId,userId)
                .eq(LitemallIntegralLog::getId,id)
                .orderByDesc(LitemallIntegralLog::getAddTime)
        );
        if(integralLogVo.getOrderId()==null){
            integralLogVo.setGoodsName(Arrays.asList("-- -- --"));
            integralLogVo.setShopName("-- -- --");
        }
        return ResponseUtil.ok(integralLogVo);
    }


    public Response integralChangeLogDetails(Integer orderId,Integer userId) {
        List<LitemallIntegralLog> litemallIntegralLogs = integralLogService.list(Wrappers.lambdaQuery(LitemallIntegralLog.class)
                .eq(LitemallIntegralLog::getOrderId, orderId)
                .eq(LitemallIntegralLog::getUserId, userId));
        return ResponseUtil.ok(litemallIntegralLogs);
    }
}
